﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil;

namespace devtm.Aop.Extensions
{
    
    
    public static class MethodReferenceExt
    {
   


        public static MethodReference GetGeneric(this MethodReference reference)
        {
            if (reference.DeclaringType.HasGenericParameters)
            {
                var declaringType = new GenericInstanceType(reference.DeclaringType);

                //declaringType.GenericArguments.AddRange(ref)

                foreach (var parameter in reference.DeclaringType.GenericParameters)
                {
                    declaringType.GenericArguments.Add(parameter);
                }
                var methodReference = new MethodReference(reference.Name, reference.MethodReturnType.ReturnType, declaringType);
                foreach (var parameterDefinition in reference.Parameters)
                {
                    methodReference.Parameters.Add(parameterDefinition);
                }
                methodReference.HasThis = reference.HasThis;

                return methodReference;
            }

            return reference;
        }




        public static MethodReference CloseMethod(this MethodReference method, IEnumerable<TypeReference> genericArguments)
        {
            if (!method.IsGenericInstance) return method;
            var methodInstance = new GenericInstanceMethod(method.Resolve());
            methodInstance.GenericArguments.AddRange(genericArguments);
            return methodInstance;
        }


        public static MethodDefinition GetDefinition(this MethodReference method)
        {
            MethodDefinition m = method as MethodDefinition;
            if (m != null)
                return m;

            return method.Resolve();

        }


        public static MethodReference DuplicateReference(this MethodReference reference)
        {

            var methodReference = new MethodReference(reference.Name, reference.MethodReturnType.ReturnType, reference.DeclaringType);

            foreach (var parameterDefinition in reference.Parameters)            
                methodReference.Parameters.Add(parameterDefinition);
            
            methodReference.HasThis = reference.HasThis;

            return methodReference;
          
        }
    }


}
